﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Runtime.Serialization;

namespace CGOnline.Server.Core
{

    //[AttributeUsage(AttributeTargets.Property)]
    //public class ConfigConstraintAttribute:Attribute
    //{
    //    public string ConstraintRule { set; get; }
    //}

    [DataContract(Namespace = "CGOnline.Server.Core.ConfigBase")]
    [StateAnnouncement(StateGroup = CONFIG_STATEGROUP, StateName = CONFIG_STATEGROUP_NORESTRICT)]
    [StateAnnouncement(StateGroup = CONFIG_STATEGROUP, StateName = CONFIG_STATEGROUP_INITIALIZE)]
    [StateAnnouncement(StateGroup = CONFIG_STATEGROUP, StateName = CONFIG_STATEGROUP_INSTANCE)]
    [StateAnnouncement(StateGroup = CONFIG_STATEGROUP, StateName = CONFIG_STATEGROUP_READONLY)]
    public class ConfigBase : RestrictStateObject, INotifyPropertyChanged
    {
        public const string CONFIG_STATEGROUP = "ConfigStates";
        public const string CONFIG_STATEGROUP_NORESTRICT = "NoRestrict";
        public const string CONFIG_STATEGROUP_INITIALIZE = "Initialize";
        public const string CONFIG_STATEGROUP_INSTANCE = "Instance";
        public const string CONFIG_STATEGROUP_READONLY = "Readonly";

        public ConfigBase(AccessRestrictions ar)
            : base(ar)
        { }

        protected void OnPropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
                PropertyChanged(this,new PropertyChangedEventArgs(propertyname));
        }

        public bool Merge(ConfigBase config2)
        {
            Type srccfgtype = config2.GetType();
            Type dstcfgtype = this.GetType();
            if (dstcfgtype.IsSubclassOf(srccfgtype) ||
                dstcfgtype == srccfgtype)
            {
                foreach (var property in srccfgtype.GetProperties())
                    property.SetValue(this,
                        property.GetValue(config2, null),
                        null);
                return true;
            }
            else
                return false;
        }

        public ConfigBase Copy()
        {
            Type cfgtype = this.GetType();
            ConfigBase cpycfg;
            try
            {
                cpycfg = Activator.CreateInstance(cfgtype) as ConfigBase;
            }
            catch (Exception ex)
            {
                throw new Exception("Error occured while creating new instance of Config type." +
                " This may caused by type lack non-param.",
                ex);
            }
            cpycfg.Merge(this);
            return cpycfg; 
        }

        //public StateObject Host { set; get; }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}
